package kit.token;

import java.security.Key;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.jose4j.json.internal.json_simple.JSONObject;
import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
import org.jose4j.jwe.JsonWebEncryption;
import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.keys.AesKey;
import org.jose4j.keys.HmacKey;
import org.jose4j.lang.JoseException;

import com.jfinal.plugin.ehcache.CacheKit;

/**
 * Utility to build JWT Token.
 * 
 * @author Paras.
 */
public class TokenBuilder {
	
	private static final String IDENTITY = "identity";
	
	public static String generate(String appkey, Map<String, Object> claimMap) throws JoseException {
		String token = null;
		TokenConfiguration tokenconfig = CacheKit.get("oauth", appkey);
		if (tokenconfig != null) {
			byte[] key = tokenconfig.getTokenKey().getBytes();

			String issuer = tokenconfig.getIssuer();
			String audience = tokenconfig.getAudience();
			String subject = tokenconfig.getSubject();

			int tokenExpirationTime = tokenconfig.getTimeout();

			JwtClaims claims = new JwtClaims();

			if (StringUtils.isNotBlank(issuer)) {
				claims.setIssuer(issuer);
			}

			if (StringUtils.isNotBlank(audience)) {
				claims.setAudience(audience);
			}

			if (StringUtils.isNotBlank(subject)) {
				claims.setSubject(subject);
			}

			claims.setExpirationTimeMinutesInTheFuture(tokenExpirationTime);
			claims.setIssuedAtToNow();

			String mapString = new JSONObject(claimMap).toString();

			claims.setClaim(IDENTITY, encrypt(mapString, tokenconfig.getEncryptionKey()));

			JsonWebSignature webSignature = new JsonWebSignature();

			webSignature.setPayload(claims.toJson());
			webSignature.setKey(new HmacKey(key));
			webSignature.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA512);
			webSignature.setDoKeyValidation(false);// 不验证密钥
			token = webSignature.getCompactSerialization();
		}
		return token;
	}

    
    /**
     * Encryption Utility to encrypt sensitive information.
     * @throws JoseException 
     */
    private static String encrypt( String message, String key ) throws JoseException {
        
        Key aesKey = new AesKey( key.getBytes() );
        
        JsonWebEncryption encryption = new JsonWebEncryption();
        
        encryption.setPlaintext( message );
        encryption.setAlgorithmHeaderValue( KeyManagementAlgorithmIdentifiers.A128KW);
        encryption.setEncryptionMethodHeaderParameter( ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256 );
        encryption.setKey( aesKey );
        
        return encryption.getCompactSerialization();
    }
}